/** 
 ** Copyright (c) 2010 Ushahidi Inc
 ** All rights reserved
 ** Contact: team@ushahidi.com
 ** Website: http://www.ushahidi.com
 ** 
 ** GNU Lesser General Public License Usage
 ** This file may be used under the terms of the GNU Lesser
 ** General Public License version 3 as published by the Free Software
 ** Foundation and appearing in the file LICENSE.LGPL included in the
 ** packaging of this file. Please review the following information to
 ** ensure the GNU Lesser General Public License version 3 requirements
 ** will be met: http://www.gnu.org/licenses/lgpl.html.	
 **	
 **
 ** If you have questions regarding the use of this file, please contact
 ** Ushahidi developers at team@ushahidi.com.
 ** 
 **/

package com.ushahidi.android.app;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.ushahidi.android.app.AroundMeMap.MapMarker;
import com.ushahidi.android.app.data.IncidentsData;
import com.ushahidi.android.app.data.ResourceData;
import com.ushahidi.android.app.data.UshahidiDatabase;
import com.ushahidi.android.app.net.AroundMeNetRequest;
import com.ushahidi.android.app.util.Util;

import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ResourceMap extends MapActivity {
    private MapView mapView = null;

    private static final int HOME = Menu.FIRST + 1;

    private static final int LIST_INCIDENT = Menu.FIRST + 2;

    private static final int INCIDENT_ADD = Menu.FIRST + 3;

    private static final int INCIDENT_REFRESH = Menu.FIRST + 4;

    private static final int SETTINGS = Menu.FIRST + 5;

    private static final int ABOUT = Menu.FIRST + 6;

    private static final int GOTOHOME = 0;

    private static final int ADD_INCIDENTS = 1;

    private static final int LIST_INCIDENTS = 2;

    private static final int REQUEST_CODE_SETTINGS = 1;

    private static final int REQUEST_CODE_ABOUT = 2;

    private static final int DIALOG_MESSAGE = 0;

	private static double MAP_SEARCH_RANGE = 0.5;

    // Oceanmaster
    private static double              holder_latitude;

    private static double              holder_longitude;
    // end

    public static Geocoder             mGc;

    private static List<IncidentsData> tmpResourcesPile;
    private static List<IncidentsData> NearbyResources;
    // OceanMaster Generally, ResourceData is the same as IncidentsData.....
    // But IncidentsData is supported by library

    private Bundle                     extras;

    private String                     reportLatitude;

    private String                     reportLongitude;

    private String                     reportTitle;

    private String                     reportDescription;

    public List<Drawable>              markers;

    private boolean                    GPSUpdated            = false;

    //OceanMaster
    // private boolean GPSUpdated = false;
    // OceanMaster, used to mark if GPS is updated
    private int                        GPSCount=0;
    // How many times GPS data has been updated.
    // 1 time per second
    private final int                  updateCycle           = 20;
    // The cycle of Gps drawing map.
    //Add end
    private static double latitude;

    private static double longitude;

    public static Geocoder gc;
    
    //IMPORTANT!!!
    //Assume updateNearBy will only be called by Location Listener.
    //So latitude and longitude is updated.
    GeoPoint position;

    private static List<IncidentsData> mNewResources;
    
    private static List<IncidentsData> mNewIncidents;
    //TODO originally not static; not sure if it will cause trouble
    //OceanMaster
    
    private static List<ResourceData> tmpResourcePile;

    private Handler mHandler;

    private int id=-1;

    private String catid;

    public Drawable marker;
    
    //By Oceanmaster, to record is self main 
    private Boolean isMainMap=false;
    
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        UshahidiPref.resourceFilterByID=getIntent().getExtras().getInt("catid")+"";
        mNewResources = new ArrayList<IncidentsData>();
        marker = getResources().getDrawable(R.drawable.marker);
        marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
        LoadMarkers();       
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.incidents_map);
        mapView = (MapView)findViewById(R.id.map);
        mapView.getController().setZoom(15);
        mGc = new Geocoder(this, Locale.US);

    	readyLocationService();// make sure current location and pick right
    	                       // detail level
    	
        tmpResourcePile = new ArrayList<ResourceData>();
        
        mHandler = new Handler();

        //      UshahidiPref.MainMap = IncidentMap.this; 
        //        //By OceanMaster; TODO Register  
        //        //Problem is how to judge this is the Main Map?
        //New Approach:
        isMainMap = getIntent().getBooleanExtra("MainMap", false);
        

        if (mNewResources.size() > 0) {
            if (id > 0) {
            	ResourceMap.latitude = Double.parseDouble(reportLatitude);
            	ResourceMap.longitude = Double.parseDouble(reportLongitude);
            } else {
            	ResourceMap.latitude = Double.parseDouble(mNewResources.get(0)
                        .getIncidentLocLatitude());
            	ResourceMap.longitude = Double.parseDouble(mNewResources.get(0)
                        .getIncidentLocLongitude());

            }

            mapView.getController()
                    .setCenter(getPoint(ResourceMap.latitude, ResourceMap.longitude));

            mapView.getController().setZoom(10);

            mapView.setBuiltInZoomControls(true);

            mHandler.post(mMarkersOnMap);

        } else {
            Toast.makeText(ResourceMap.this, "There are no reports to be shown", Toast.LENGTH_LONG)
                    .show();
        }

    }
    //By OceanMaster
    String oldFilter="";
    public void updateMap()
    {
	if(UshahidiPref.resourceFilterByID.equals(oldFilter))
	    return;
	oldFilter=UshahidiPref.resourceFilterByID;
	this.QueryNearBy(UshahidiPref.resourceFilterByID);
	drawNearByMap();
    }

    @Override
    protected boolean isRouteDisplayed() {
        return (false);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_I) {
            // Zoom not closer than possible
            mapView.getController().zoomIn();
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_O) {
            // Zoom not farer than possible
            mapView.getController().zoomOut();
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_T) {
            // Switch to satellite view
            mapView.setSatellite(true);

            return true;
        } else if (keyCode == KeyEvent.KEYCODE_M) {
            // Switch to satellite view
            mapView.setSatellite(false);

            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    // get resource from the db
    public  List<IncidentsData> showResources(String by) {
    	//Modified by yujie chen
    	mNewResources.clear();
        String title;
        String status;
        String date;
        String description;
        String location;
        String categories;
        String media;
        String image;
        String thumbnails[];
        Drawable d = null;
        mNewResources=this.QueryNearBy(by);
    	if(!mNewResources.isEmpty())
    	{       
    		return mNewResources;
    	}
    	else{
        	
            Cursor cursor;
            if ( by.length()==0 ||by.equals(UshahidiPref.all))
                cursor = UshahidiApplication.mDb.fetchAllResources();
            else
                cursor = UshahidiApplication.mDb.fetchNearByResourceByCatId(holder_latitude,holder_longitude,MAP_SEARCH_RANGE,by);

            if (cursor.moveToFirst()) {
                int idIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_ID);
                int titleIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_TITLE);
                int dateIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_DATE);
                int verifiedIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_VERIFIED);
                int locationIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_LOC_NAME);

                int descIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_DESC);

                int categoryIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_CATEGORIES);

                int mediaIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_MEDIA);

                int imageIndex = cursor.getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_IMAGE);

                int latitudeIndex = cursor
                        .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_LOC_LATITUDE);

                int longitudeIndex = cursor
                        .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_LOC_LONGITUDE);

                mNewResources.clear();

                do {

                    ResourceData resourceData = new ResourceData();
                    mNewResources.add(resourceData);
                    ListIncidentText listText = new ListIncidentText();

                    int id = Util.toInt(cursor.getString(idIndex));
                    resourceData.setResourceId(id);
                    resourceData.setResourceLocLatitude(cursor.getString(latitudeIndex));
                    resourceData.setResourceLocLongitude(cursor.getString(longitudeIndex));

                    title = cursor.getString(titleIndex);
                    resourceData.setResourceTitle(title);
                    listText.setTitle(Util.capitalize(title));

                    description = cursor.getString(descIndex);
                    resourceData.setResourceDesc(description);
                    listText.setDesc(description);

                    categories = cursor.getString(categoryIndex);
                    resourceData.setResourceCategories(categories);
                    listText.setCategories(Util.capitalize(categories));

                    location = cursor.getString(locationIndex);
                    resourceData.setResourceLocation(location);
                    listText.setLocation(Util.capitalize(location));

                    date = Util.formatDate("yyyy-MM-dd HH:mm:ss", cursor.getString(dateIndex),
                            "MMMM dd, yyyy 'at' hh:mm:ss aaa");

                    resourceData.setResourceDate(date);
                    listText.setDate(date);

                    media = cursor.getString(mediaIndex);
                    resourceData.setResourceThumbnail(media);
                    listText.setMedia(media);

                    thumbnails = media.split(",");
                    // TODO do a proper check for thumbnails
                    if (!TextUtils.isEmpty(thumbnails[0])) {
                        d = ImageManager.getImages(thumbnails[0]);
                    } else {
                        d = null;
                    }
                    image = cursor.getString(imageIndex);
                    resourceData.setResourceImage(image);
                    resourceData.setResourceVerified(Util.toInt(cursor.getString(verifiedIndex)));
                } while (cursor.moveToNext());
            }
        cursor.close();
    	}
        return mNewResources;

    }

    /********************
     * Main Life Cycle OceanMaster
     ********************/

    @Override
    public void onResume()
    {
	Log.v("Oceanmaster", "Around Me Resumed");
	readyLocationService();
	super.onResume();
    }

    @Override
    protected void onDestroy()
    {
	unregisterListeners();
	GPSUpdated = false;
	super.onDestroy();
    }

    @Override
    protected void onPause()
    {
	unregisterListeners();
	GPSUpdated = false;
	// SharedPreferences.Editor editor = getPreferences(0).edit();
	// editor.putString("title", mIncidentTitle.getText().toString());
	// editor.putString("desc", mIncidentDesc.getText().toString());
	// editor.putString("location", mIncidentLocation.getText().toString());
	// editor.commit();
	super.onPause();
    }

    @Override
    protected void onStop()
    {
	unregisterListeners();
	GPSUpdated = false;
	super.onStop();
    }
    
    /********************
     * Data Fetching
     ********************/
    double MinDistance = 0.001; //In degree
    public boolean farEnoughToUpdate()
    {
	return (Math.abs(old_holder_latitude - holder_latitude)+Math.abs(old_holder_longitude - holder_longitude) > MinDistance);
    }
    
    
    static double old_holder_latitude;
    static double old_holder_longitude;
    
    private void updateNearBy()
    {
    	
    GPSCount = (GPSCount+1) % updateCycle;
    	
    //Update 'me' position
    position = getPoint(holder_latitude, holder_longitude);
    	
    if(me == null)
    {
       me = new MapMarker(markers.get(0), position.getLatitudeE6(), position.getLongitudeE6());
       mapView.getOverlays().add(me);
    }	
    else
    	me.updateLocation(position.getLatitudeE6(), position.getLongitudeE6());
    	
    if(GPSCount!=1)
    	    return;
	//mNewResources = showResources(UshahidiPref.resourceFilterByID);
    this.QueryNearBy(UshahidiPref.resourceFilterByID);
	NearbyResources = mNewResources;
	if (NearbyResources.size() > 0)
	{
	    // TODO to be changed according to user range
	    // mapView.getController().setZoom(5);
	    mHandler.post(mMarkersOnMap);
	    // Draw Markers on Map
	}
	else
	{
	    Toast.makeText(ResourceMap.this,
		    "There are no resources in selected range with lat:"+holder_latitude+" long: "+holder_longitude,
		    Toast.LENGTH_LONG).show();
	}
    }

    /********************
     * Geo Location related function OceanMaster
     ********************/
    LocationManager                         manager;
    long                                    updateTimeMsec = 1000;
    float                                   updateDistance = 0;
    LocationProvider                        high;
    LocationProvider                        low;
    private MultiTimeDeviceLocationListener high_listener  = null;
    private OneTimeDeviceLocationListener   low_listener   = null;

    private void registerHighOneTimeListener()
    {
	high_listener = new MultiTimeDeviceLocationListener();
	manager.requestLocationUpdates(high.getName(), updateTimeMsec,
	        updateDistance, high_listener);
	
    }

    private void registerLowOneTimeListener()
    {
	low_listener = new OneTimeDeviceLocationListener();
	manager.requestLocationUpdates(low.getName(), 100, updateDistance,
	        low_listener);
    }

    private void unregisterListeners()
    {
	if (high_listener != null)
	{
	    manager.removeUpdates(high_listener);
	    high_listener = null;
	}
	if (low_listener != null)
	{
	    manager.removeUpdates(low_listener);
	    low_listener = null;
	}
    }

    // Fetches the current location of the device.
    // create two different listeners, one for once, one for long
    // temporarily, periodical location service is not needed because
    // we are not following user
    private void readyLocationService()
    {
	// ===============================
	// ready one time location request
	// ===============================
	// listener = new OneTimeDeviceLocationListener();
	manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

	// get low and high accuracy provider
	// this is tempararily changed, due to simulation
	// low = manager.getProvider(manager.getBestProvider(
	// Util.createCoarseCriteria(), true));
	// high = manager.getProvider(manager.getBestProvider(
	// Util.createFineCriteria(), true));

	low = manager.getProvider(manager.NETWORK_PROVIDER);
	high = manager.getProvider(manager.GPS_PROVIDER);

	// imediately register 2 one time service to update location
	unregisterListeners();
	registerHighOneTimeListener();
	registerLowOneTimeListener();
    }

    public GeoPoint getPoint(double lat, double lon)
    {
	return (new GeoPoint((int) (lat * 1000000.0), (int) (lon * 1000000.0)));
    }

    // get the current location of the device/user
    public class OneTimeDeviceLocationListener implements LocationListener
    {
	OneTimeDeviceLocationListener()
	{
	    super();
	    Log.v("Oceanmaster", "new OneTimeListener Created");
	}

	public void onLocationChanged(Location location)
	{
	    if (location != null)
	    {
		manager.removeUpdates(OneTimeDeviceLocationListener.this);

		GPSUpdated = true;
		holder_latitude = location.getLatitude();
		holder_longitude = location.getLongitude();
		ClearMap();
		centerLocation(getPoint(holder_latitude, holder_longitude));
		Log.v("Oceanmaster", "Location Changed : " + holder_latitude
		        + " , " + holder_longitude);
		updateNearBy();
		GPSCount--;
		// mReportLocation.setText(String.valueOf(holder_latitude) +
		// ", " + String.valueOf(holder_longitude));
	    }
	}

	public void onProviderDisabled(String provider)
	{
	    Util.showToast(ResourceMap.this, R.string.location_not_found);
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Disabled");
	}

	public void onProviderEnabled(String provider)
	{
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Enabled");
	}

	public void onStatusChanged(String provider, int status, Bundle extras)
	{
	}
    }

    public class MultiTimeDeviceLocationListener implements LocationListener
    {
	MultiTimeDeviceLocationListener()
	{
	    super();
	    Log.v("Oceanmaster", "new MultiTimeListener Created");
	}

	public void onLocationChanged(Location location)
	{
	    if (location != null)
	    {
		GPSUpdated = true;
		holder_latitude = location.getLatitude();
		holder_longitude = location.getLongitude();
		ClearMap();
		centerLocation(getPoint(holder_latitude, holder_longitude));
		//mNewResources = showResources(UshahidiPref.resourceFilterByID);
		updateNearBy();
		// mReportLocation.setText(String.valueOf(holder_latitude) +
		// ", " + String.valueOf(holder_longitude));
		Log.v("Oceanmaster", "Location Changed : " + holder_latitude
		        + " , " + holder_longitude);
	    }
	}

	public void onProviderDisabled(String provider)
	{
	    Util.showToast(ResourceMap.this, R.string.location_not_found);
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Disabled");
	}

	public void onProviderEnabled(String provider)
	{
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Enabled");
	}

	public void onStatusChanged(String provider, int status, Bundle extras)
	{

	}
    }

    
/////////////////////////////////////////////////////////////////////////////////////////
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
    }

    // menu stuff
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        populateMenu(menu);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        populateMenu(menu);

        return (super.onCreateOptionsMenu(menu));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // applyMenuChoice(item);

        return (applyMenuChoice(item) || super.onOptionsItemSelected(item));
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        return (applyMenuChoice(item) || super.onContextItemSelected(item));
    }

    protected Dialog onCreateDialog(int id, String message, String title) {
        switch (id) {
            case DIALOG_MESSAGE: {
                AlertDialog dialog = (new AlertDialog.Builder(this)).create();
                dialog.setTitle(title);
                dialog.setMessage(message);
                dialog.setButton2("Ok", new Dialog.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                dialog.setCancelable(false);
                return dialog;
            }
        }
        return null;
    }

    private void populateMenu(Menu menu) {
        MenuItem i;
        i = menu.add(Menu.NONE, HOME, Menu.NONE, R.string.menu_home);
        i.setIcon(R.drawable.ushahidi_home);

        i = menu.add(Menu.NONE, INCIDENT_ADD, Menu.NONE, R.string.incident_menu_add);
        i.setIcon(R.drawable.ushahidi_add);

        i = menu.add(Menu.NONE, LIST_INCIDENT, Menu.NONE, R.string.incident_list);
        i.setIcon(R.drawable.ushahidi_list);

        i = menu.add(Menu.NONE, INCIDENT_REFRESH, Menu.NONE, R.string.incident_menu_refresh);
        i.setIcon(R.drawable.ushahidi_refresh);

        i = menu.add(Menu.NONE, SETTINGS, Menu.NONE, R.string.menu_settings);
        i.setIcon(R.drawable.ushahidi_settings);

        i = menu.add(Menu.NONE, ABOUT, Menu.NONE, R.string.menu_about);
        i.setIcon(R.drawable.ushahidi_about);

    }

    /********************
     * Tasks OceanMaster
     ********************/
    // The thread to populate map
    final Runnable mMarkersOnMap = new Runnable()
	                         {
	                             public void run()
	                             {
	                            	 drawNearByMap();
	                             }
	                         };

    private class QueryTask extends AsyncTask<Void, Void, Integer>
    {

	protected Integer status;
	protected Context appContext;

	@Override
	protected void onPreExecute()
	{
	    setProgressBarIndeterminateVisibility(true);
	}

	@Override
	protected Integer doInBackground(Void... params)
	{
	    status = Util.processReports(appContext);
	    return status;
	}

	// OceanMaster: onPost... is checking the number returned by doIn...

	@Override
	protected void onPostExecute(Integer result)
	{
	    if (result == 4)
	    {
		Util.showToast(appContext, R.string.internet_connection);
	    }
	    else if (result == 0)
	    {
		NearbyResources = QueryNearBy(UshahidiPref.resourceFilterByID);
		drawNearByMap();
		setProgressBarIndeterminateVisibility(false);
	    }
	}
    }

    private boolean applyMenuChoice(MenuItem item) {
        Intent intent;
        switch (item.getItemId()) {
            case HOME:
                intent = new Intent(ResourceMap.this, Ushahidi.class);
                startActivityForResult(intent, GOTOHOME);
                return true;
            case INCIDENT_REFRESH:
            	QueryTask queryTask = new QueryTask();
                queryTask.appContext = this;
                queryTask.execute();
                return (true);

            case LIST_INCIDENT:
                extras = new Bundle();
                extras.putInt("tab_index", 0);
                intent = new Intent(ResourceMap.this, IProvide.class);
                intent.putExtra("tab", extras);
                startActivityForResult(intent, LIST_INCIDENTS);
                return (true);

            case INCIDENT_ADD:
                intent = new Intent(ResourceMap.this, AddIncident.class);
                startActivityForResult(intent, ADD_INCIDENTS);
                return (true);

            case ABOUT:
                intent = new Intent(ResourceMap.this, About.class);
                startActivityForResult(intent, REQUEST_CODE_ABOUT);
                setResult(RESULT_OK);
                return true;

            case SETTINGS:
                intent = new Intent(ResourceMap.this, Settings.class);

                // Make it a subactivity so we know when it returns
                startActivityForResult(intent, REQUEST_CODE_SETTINGS);
                return (true);
        }
        return false;
    }

public List<IncidentsData> QueryNearBy(String by) {
	// TODO: change to web based data

	mNewResources.clear();// by OceanMaster

	JSONArray results;
	results = AroundMeNetRequest.getNearByResourceFromWeb(1, true,
	        holder_latitude, holder_longitude);

	if (results == null)// 没有结果
	    return mNewResources;

	String title;
	String description;
	String location;
	String categories;
	String thumbnail;
	String image;

	try
	{

	    for (int i = 0; i < results.length(); i++)
	    {
		JSONObject cursor = results.optJSONObject(i);

		JSONObject resource = cursor.getJSONObject("resource");
		JSONArray cates = cursor.getJSONArray("categories");

		IncidentsData incidentData = new IncidentsData();
		mNewResources.add(incidentData);

		int id = resource.getInt("resourceid");
		incidentData.setIncidentId(id);

		title = Util.capitalizeString(resource
		        .getString("resourcetitle"));
		incidentData.setIncidentTitle(title);

		description = resource.getString("resourcedescription");
		incidentData.setIncidentDesc(description);

		categories = "";
		for (int j = 0; j < cates.length(); j++)
		    categories += cates.optJSONObject(j)
			    .getJSONObject("category").getString("title");
		incidentData.setIncidentCategories(categories);

		// Updated to here!!!s
		location = resource.getString("locationname");
		incidentData.setIncidentLocLongitude(location);

		Util.joinString("Date: ", resource.getString("resourcedate"));
		incidentData
		        .setIncidentDate(resource.getString("resourcedate"));

		// thumbnail = resource.getString("resourceid");;
		// incidentData.setIncidentThumbnail(thumbnail);

		// image = resource.getString("resourceid");;
		// incidentData.setIncidentImage(image);

		incidentData.setIncidentVerified(resource
		        .getInt("resourceverified"));

		incidentData.setIncidentLocLatitude(resource
		        .getString("locationlatitude"));

		incidentData.setIncidentLocLongitude(resource
		        .getString("locationlongitude"));

		Log.v("Oceanmaster",
		        "One Row: lat = "
		                + incidentData.getIncidentLocLatitude()
		                + " , long = "
		                + incidentData.getIncidentLocLongitude()
		                + " , category = " + categories);

	    }
	}
	catch (JSONException e)
	{
		mNewResources.clear();// by OceanMaster
	    Log.v("Oceanmaster",
		    "ERROR occured during Processing in Around Me Page");
	}

	return mNewResources;
	}
	////////////////////////////////////////////////////////////
    /********************
     * Draw Map related OceanMaster
     ********************/
    MapMarker me = null;	//The Marker denotes 'me'
        
    private void ClearMap()
    {
	mapView.getOverlays().clear();
    }

    // 0: me
    // 1: hospital
    // 2: shelter
    // 3: water
    // 4: food
    // 5: heavy equipment
    // 6: generic
    public void LoadMarkers()
    {
	// Oceanmaster
	// ------------------------
	// Load Icons
	// ------------------------
	markers = new ArrayList<Drawable>();

	Drawable marker;

	marker = getResources().getDrawable(R.drawable.me);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_hospital);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_shelter);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_drinking_water);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_food);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_heavy_equipment);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_generic);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);
    }

    // add markers to the map
    private void drawNearByMap()
    {
	//GeoPoint position;
	//int iconindex = 0;

	// 1:Mark self on map
	// there is a clear map above
	//position = getPoint(holder_latitude, holder_longitude);
	//PlaceSingleMarker(position.getLatitudeE6(), position.getLongitudeE6(),0);
	if(me == null)
	    me = new MapMarker(markers.get(0), position.getLatitudeE6(), position.getLongitudeE6());
	else
	    me.updateLocation(position.getLatitudeE6(), position.getLongitudeE6());
	mapView.getOverlays().add(me);
	
	// 2:Others
	// Approach 1:
	/*
	 * if (false) for (IncidentsData data : NearbyResources) { position =
	 * getPoint( Double.parseDouble(data.getIncidentLocLatitude()),
	 * Double.parseDouble(data.getIncidentLocLongitude())); String cates =
	 * data.getIncidentCategories();
	 * 
	 * if (cates.contains("Hospital")) iconindex = 1; else if
	 * (cates.contains("Shelter")) iconindex = 2; else if
	 * (cates.contains("Water")) iconindex = 3; else iconindex = 4;
	 * 
	 * PlaceSingleMarker(position.getLatitudeE6(),
	 * position.getLongitudeE6(), iconindex); Log.v("Oceanmaster",
	 * "New mark should be placed, type = " + iconindex); }
	 * 
	 * // Approcah 2 TODO else {
	 */
	// Me
	// Hospital
	List<IncidentsData> hospital = new ArrayList<IncidentsData>();
	// Shelter
	List<IncidentsData> shelter = new ArrayList<IncidentsData>();
	// Water
	List<IncidentsData> water = new ArrayList<IncidentsData>();
	// Food
	List<IncidentsData> food = new ArrayList<IncidentsData>();
	// Heavy equipments
	List<IncidentsData> equip = new ArrayList<IncidentsData>();
	// Generc
	List<IncidentsData> generic = new ArrayList<IncidentsData>();

	for (IncidentsData data : NearbyResources)
	{
	    String cates = data.getIncidentCategories();

	    if (cates.contains("Hospital"))
	    {
		hospital.add(data);
		continue;
	    }
	    else if (cates.contains("Temporary Shelter"))
	    {
		shelter.add(data);
		continue;
	    }
	    else if (cates.contains("Drinking Water"))
	    {
		water.add(data);
		continue;
	    }
	    else if (cates.contains("Food"))
	    {
		food.add(data);
		continue;
	    }
	    else if (cates.contains("Heavy Equipment"))
	    {
		equip.add(data);
		continue;
	    }

	    else
		generic.add(data);
	}

	if (hospital.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, hospital, 1));
	if (shelter.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, shelter, 2));
	if (water.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, water, 3));
	if (food.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, food, 4));
	if (equip.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, equip, 5));
	if (generic.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, generic, 6));

	Log.v("Oceanmaster",
	        "Populate Marker Over; Hospitals:" + hospital.size()
	                + " shelters:" + shelter.size() + " water:"
	                + water.size() + " food:" + food.size()
	                + " equipments:" + equip.size() + " others:"
	                + generic.size());
	/* } */
    }
    
    private void PlaceSingleMarker(int markerLatitude, int markerLongitude,
	    int iconindex)
    {
	// mapView.getOverlays().clear();
	me =  new MapMarker(markers.get(iconindex), markerLatitude,
                markerLongitude);
	mapView.getOverlays().add(me);
    }

    // Modified by OceanMaster, added updateText argument
    private void centerLocation(GeoPoint centerGeoPoint)
    {
	mapView.getController().animateTo(centerGeoPoint);
	// latitude = centerGeoPoint.getLatitudeE6() / 1.0E6;
	// longitude = centerGeoPoint.getLongitudeE6() / 1.0E6;
	// if (updateText)
	// mIncidentLocation.setText(getLocationFromLatLon(latitude,longitude));
	// PlaceSingleMarker(centerGeoPoint.getLatitudeE6(),centerGeoPoint.getLongitudeE6(),0);
    }

    private void setLocationBySearch(String search)
    {
	Log.v("Oceanmaster", "setLocationBySearch : " + search);
	if (search == null || search.length() == 0)
	{
	    Util.showToast(ResourceMap.this,
		    "Please fill search field first to find location");
	    return;
	}
	try
	{
	    List<Address> result = mGc.getFromLocationName(search, 1);
	    if (result.size() <= 0)
	    {
		Util.showToast(ResourceMap.this, "No result found");
		return;
	    }

	    Address location = result.get(0);

	    latitude = location.getLatitude();
	    longitude = location.getLongitude();

	    centerLocation(getPoint(latitude, longitude));
	    // mReportLocation.setText(String.valueOf(latitude) + ", " +
	    // String.valueOf(longitude));

	}
	catch (IOException e)
	{
	    Util.showToast(ResourceMap.this,
		    "Error occured while trying to search Location");
	}
    }

    private List<Address> mFoundAddresses;

    // get the real location name from the latitude and longitude.
    private String getLocationFromLatLon(double lat, double lon)
    {
	Log.v("Oceanmaster", "Location name service requested");
	try
	{
	    Address address;
	    mFoundAddresses = mGc.getFromLocation(lat, lon, 2);
	    if (mFoundAddresses.size() > 0)
	    {
		address = mFoundAddresses.get(0);
		return address.getSubAdminArea();
	    }
	    else
	    {
		return "";
	    }
	}
	catch (IOException e)
	{
	    e.printStackTrace();
	}
	return "";
    }

    public class MapMarker extends ItemizedOverlay<OverlayItem>
    {

	private List<OverlayItem> locations = new ArrayList<OverlayItem>();

	private Drawable          marker;

	private OverlayItem       myOverlayItem;

	public MapMarker(Drawable defaultMarker, int LatitudeE6, int LongitudeE6)
	{
	    super(defaultMarker);
	    this.marker = defaultMarker;

	    // create locations of interest
	    GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6);

	    myOverlayItem = new OverlayItem(myPlace, " ", " ");

	    locations.add(myOverlayItem);

	    populate();

	}

	// Added by OceanMaster, not tested
	public void updateLocation(int LatitudeE6, int LongitudeE6)
	{
	    locations.clear();
	    GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6);
	    myOverlayItem = new OverlayItem(myPlace, " ", " ");
	    locations.add(myOverlayItem);
	    populate();
	}
	
	// Added by OceanMaster, not tested
	public void addLocation(int LatitudeE6, int LongitudeE6)
	{
	    GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6);
	    myOverlayItem = new OverlayItem(myPlace, " ", " ");
	    locations.add(myOverlayItem);
	    populate();
	}

	@Override
	protected OverlayItem createItem(int i)
	{
	    return locations.get(i);
	}

	@Override
	public int size()
	{
	    return locations.size();
	}

	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow)
	{
	    super.draw(canvas, mapView, shadow);
	    // TODO
	    // Changed by OceanMaster!
	    // New icon is not bottom_centered
	    boundCenter(marker);
	    // boundCenterBottom(marker);
	}
    }

    private class SitesOverlay extends UshahidiItemizedOverlay<OverlayItem>
    {
	private ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();

	public SitesOverlay(MapView mapView, List<IncidentsData> Resources,
	        int iconindex)
	{
	    // changed from boundCenterBottom to boundCenter
	    super(boundCenter(markers.get(iconindex)), mapView,
		    ResourceMap.this, Resources, extras);
	    mapView.getContext();

	    for (IncidentsData resourceData : Resources)
	    {
	    	ResourceMap.latitude = Double.parseDouble(resourceData
		        .getIncidentLocLatitude());
	    	ResourceMap.longitude = Double.parseDouble(resourceData
		        .getIncidentLocLongitude());

		items.add(new OverlayItem(getPoint(ResourceMap.latitude,
				ResourceMap.longitude),
		        resourceData.getIncidentTitle(), Util.limitString(
		                resourceData.getIncidentDesc(), 30)));
	    }

	    populate();
	}

	@Override
	protected OverlayItem createItem(int i)
	{
	    return items.get(i);
	}

	@Override
	protected boolean onBalloonTap(int i)
	{
	    return true;
	}

	@Override
	public int size()
	{
	    return (items.size());
	}
    }

    /********************
     * Ordinary stuff OceanMaster
     ********************/
}
